# -*- coding:utf-8 -*-
# Author: JianPei
# @Time : 2021/11/10 09:21
from . import api
from flask import g, request, jsonify, current_app, session
from ihome.utils.response_code import RET
from ihome.utils.image_storage import storage
from ihome import db, constants
from ihome.utils.commons import login_required
from ihome.models import Area, House, Facility, HouseImage, Order, User
from ihome import redis_store
from ihome.utils.image_storage import storage
import json
from datetime import datetime


# GET /api/v1.0/areas
@api.route('/areas', methods=['GET'])
def get_area_info():
    """获取城区信息"""
    try:
        resp_json = redis_store.get('area_info')
    except Exception as e:
        current_app.logger.error(e)
    else:
        # 如果缓存存在则返回缓存的信息，不往下执行
        if resp_json:
            current_app.logger.info('hit area info')
            return resp_json, 200, {'Content-Type': 'application/json'}
    try:
        area_li = Area.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库异常')

    area_dict_li = []
    for area in area_li:
        area_dict_li.append(area.to_dict())

    # 将数据转换成json字符串
    resp_dict = dict(errno=RET.OK, errmsg='查询成功', data=area_dict_li)
    resp_json = json.dumps(resp_dict)

    # 设置缓存
    try:
        redis_store.setex('area_info', constants.AREA_INFO_REDIS_CACHE_EXPIRES, resp_json)
    except Exception as e:
        current_app.logger.error(e)

    return resp_json, 200, {'Content-Type': 'application/json'}


# POST /api/v1.0/houses/info
@api.route('/houses/info', methods=['POST'])
@login_required
def save_house_info():
    """
    保存房屋的基本信息
    前端发送过来的json数据
    {
        "title":"",
        "price":"",
        "area_id":"",
        "address":"",
        "room_count":"",
        "acreage":"",
        "unit":"",
        "capacity":"",
        "beds":"",
        "deposit":"",
        "min_days":"",
        "max_days":"",
        "facility":["1", "2"]
    }
    :return:
    """
    # 获取数据
    user_id = g.user_id

    house_dict = request.get_json()
    title = house_dict.get('title')  # 房屋名称
    price = house_dict.get('price')  # 房屋单价
    area_id = house_dict.get('area_id')  # 房屋所属城区的编号
    address = house_dict.get('address')  # 房屋地址
    room_count = house_dict.get('room_count')  # 房屋包含的房间数目
    acreage = house_dict.get('acreage')  # 房屋面积
    unit = house_dict.get('unit')  # 房屋布局（一房一厅）
    capacity = house_dict.get('capacity')  # 房屋容纳人数
    beds = house_dict.get('beds')  # 房屋卧床数目
    deposit = house_dict.get('deposit')  # 押金
    min_days = house_dict.get('min_days')  # 最小入住天数
    max_days = house_dict.get('max_days')  # 最大入住天数

    # 校验参数
    if not all(
            [title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 判断金额是否正确
    try:
        price = int(float(price) * 100)
        deposit = int(float(deposit) * 100)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 判断城区ID是否存在
    try:
        area = Area.query.get(area_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据异常')

    if area is None:
        return jsonify(errno=RET.NODATA, errmsg='城区信息有误')

    # 保存房屋信息
    house = House(
        user_id=user_id,
        area_id=area_id,
        title=title,
        price=price,
        address=address,
        room_count=room_count,
        acreage=acreage,
        unit=unit,
        capacity=capacity,
        beds=beds,
        deposit=deposit,
        min_days=min_days,
        max_days=max_days
    )

    # 设施和房屋信息保存数据库要么一起保存成功，要么一起失败，所以保存在session中，不会操作数据库，即不用捕获异常,在下面设施提交一并操作
    db.session.add(house)
    # try:
    #     db.session.add(house)
    #     db.session.commit()
    # except Exception as e:
    #     current_app.logger.error(e)
    #     db.session.rollback()
    #     return jsonify(errno=RET.DBERR, errmsg='保存数据异常')

    # 处理房屋的设施信息
    facility_ids = house_dict.get('facility')

    # 如果用户勾选了设施信息，在保存数据库
    if facility_ids:
        try:
            facilities = Facility.query.filter(Facility.id.in_(facility_ids)).all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库异常')

        if facilities:
            # 表示有合法的设施数据
            # 保存设施数据
            house.facilities = facilities
    # 统一提交，房屋信息和设施信息
    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')

    # 保存数据成功
    return jsonify(errno=RET.OK, errmsg='OK', data={'house_id': house.id})


# POST /api/v1.0/houses/image
@api.route('/houses/image', methods=['POST'])
@login_required
def save_house_image():
    """
    保存房屋的图片
    参数 图片 房屋的id
    :return:
    """
    image_file = request.files.get('house_image')
    house_id = request.form.get('house_id')

    current_app.logger.info(image_file)
    current_app.logger.info(house_id)
    if not all([image_file, house_id]):
        return jsonify(errno=RET.PARAMERR, errmgs='参数错误')

    # 判断house_id 的正确性
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.NODATA, errmsg='数据库异常')

    if house is None:
        return jsonify(errno=RET.NODATA, errmsg='房屋不存在')

    # 将图片保存在七牛中
    image_data = image_file.read()
    try:
        file_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='保存失败')

    # 保存图片信息到数据库中
    house_image = HouseImage(house_id=house_id, url=file_name)
    db.session.add(house_image)

    # 处理房屋的主图片
    if not house.index_image_url:
        house.index_image_url = file_name
        db.session.add(house)

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存图片数据异常')

    return jsonify(errno=RET.OK, errmsg='OK', data={'image_url': file_name})


# GET /api/v1.0/user/houses
@api.route('/user/houses')
@login_required
def get_user_houses():
    """获取房东发布房源的信息"""
    user_id = g.user_id
    try:
        user = User.query.get(user_id)
        houses = user.houses
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取房源信息失败')

    # 将查询到的房屋信息转换为字典存放到列表中
    houses_list = []
    if houses:
        for house in houses:
            houses_list.append(house.to_basic_dict())
    return jsonify(errno=RET.OK, data=houses_list)


# GET /api/v1.0/houses/index
@api.route('/houses/index')
def get_house_index():
    """获取主页幻灯片展示的房源信息"""
    try:
        ret = redis_store.get('home_page_data')
    except Exception as e:
        current_app.logger.error(e)
        ret = None

    # 判断redis中是否取出数据
    if ret:
        current_app.logger.info('读了缓存数据')
        return '{"errno"="0","errmsg"="OK","data":%s}' % ret, 200, {"Content-Type": "application/json"}
    else:
        try:
            # 查询数据库，返回房屋订单最多的信息
            houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询数据失败')
        if not houses:
            return jsonify(errno=RET.NODATA, errmsg='查询无数据')

        houses_list = []
        for house in houses:
            # 如果房屋没有图片则跳过
            if not house.index_image_url:
                continue
            houses_list.append(house.to_basic_dict())

        # 将数据转换为json
        json_houses = json.dumps(houses_list)
        try:
            redis_store.setex('home_page_data', constants.HOME_PAGE_DATA_REDIS_EXPIRES, json_houses)
        except Exception as e:
            current_app.logger.error(e)

        return '{"errno"="0","errmsg"="OK","data":%s}' % json_houses, 200, {"Content-Type": "application/json"}


# GET /api/v1.0/houses/1
@api.route('/houses/<int:house_id>')
def get_house_detail(house_id):
    """获取房屋详情"""
    # 前端展示时，如果当前页面是自己发布的房源则不显示[立即预定]按钮
    # 所以需要后端返回登录的user_id
    # 获取用户的登录信息，若登录则返回user_id，否则返回-1
    user_id = session.get('user_id')

    # 查询数据库获取传入的house_id 的房源信息
    try:
        house = House.query.filter_by(id=house_id).first()
        # current_app.logger.info('house=', house)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库失败')

    if not house:
        return jsonify(errno=RET.NODATA, errmsg='没有该房源信息')

    # 将房屋对象转换成字典
    try:
        house_data = house.to_full_dict()
        current_app.logger.info('house_data', house_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据出错')

    # 添加缓存，存到redis中
    json_house = json.dumps(house_data)
    try:
        redis_store.setex('house_info_%s' % house_id, constants.HOUSE_DETAIL_REDIS_EXPIRE_SECOND, json_house)
    except Exception as e:
        current_app.logger.error(e)

    resp = '{"errno":"0","errmsg":"OK","data":{"user_id":%s,"house":%s}}' % (user_id, json_house), 200, {
        'Content-Type': 'application/json'}
    return resp


# GET /api/v1.0/houses>?sd=2021-12-01&ed=2022-01-02&aid=10&sk=new&p=1
@api.route("/houses")
def get_house_list():
    """获取房屋的列表信息"""
    start_time = request.args.get("sd", "")  # 开始时间
    end_time = request.args.get("ed", "")  # 结束时间
    area_id = request.args.get("aid", "")  # 区域id
    sort_key = request.args.get("sk", "new")  # 排序关键字
    page = request.args.get("p")  # 页数

    print("page", page)
    print("start_time", start_time)
    print("end_time", end_time)
    print("area_id", area_id)
    print("sort_key", sort_key)
    # 先读取缓存
    try:
        redis_key = "house_%s_%s_%s_%s" % (start_time, end_time, area_id, sort_key)
        resp_json = redis_store.hget(redis_key, page)
        print(resp_json)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if resp_json:
            return resp_json, 200, {"Content-Type": "application/json"}

    # 处理时间
    try:
        if start_time:
            start_time = datetime.strptime(start_time, "%Y-%m-%m")

        if end_time:
            end_time = datetime.strptime(end_time, "%Y-%m-%m")

        if start_time and end_time:
            assert start_time <= end_time
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="日期参数有误")

    # 处理区域id
    if area_id:
        try:
            area = Area.query.get(area_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg="区域ID有误")

    # 处理页数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)

        page = 1

    # 过滤条件的参数列表容器
    filter_params = []

    # 填充过滤参数
    # 时间条件
    conflict_order = None

    # 查询冲突的订单
    if start_time and end_time:
        conflict_order = Order.query.filter(Order.begin_date <= end_time, Order.end_date >= start_time)
    elif start_time:
        conflict_order = Order.query.filter(Order.end_date >= start_time)
    elif end_time:
        conflict_order = Order.query.filter(Order.begin_date <= end_time)

    if conflict_order:
        # 从订单中获取冲的房屋id
        conflict_house_ids = [order.house_id for order in conflict_order]

        # 如果冲的房屋id不为空，向查询参数中添加条件
        if conflict_house_ids:
            filter_params.append(House.id.notin_(conflict_house_ids))

    # 区域条件
    if area_id:
        filter_params.append(House.area_id == area_id)

    # 查询数据库
    if sort_key == "booking":
        house_query = House.query.filter(*filter_params).order_by(House.order_count.desc())
    elif sort_key == "price-inc":
        house_query = House.query.filter(*filter_params).order_by(House.price.asc())
    elif sort_key == "price-des":
        house_query = House.query.filter(*filter_params).order_by(House.price.desc())
    else:
        house_query = House.query.filter(*filter_params).order_by(House.create_time.desc())

    # 分页处理
    page_obj = house_query.paginate(page=page, per_page=constants.HOUSE_LIST_PAGE_CAPACITY, error_out=False)

    # 获取每页数据
    house_li = page_obj.items
    houses = []
    for house in house_li:
        houses.append(house.to_basic_dict())

    # 获取总页数
    total_page = page_obj.pages

    # 添加缓存
    resp_dict = dict(errno=RET.OK, errmsg="OK", data={"total_page": total_page, "houses": houses, "current_page": page})
    resp_json = json.dumps(resp_dict)

    # 设置缓存
    redis_key = "house_%s_%s_%s_%s" % (start_time, end_time, area_id, sort_key)
    # 哈希类型的redis
    try:
        redis_store.hset(redis_key, page, resp_json)
        redis_store.expire(redis_key, constants.HOUSE_LIST_PAGE_REDIS_CACHE_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errno=RET.OK, errmsg="OK", data={"total_page": total_page, "houses": houses, "current_page": page})
